home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / sync / syncSysV.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  17.0 KB  |  718 lines

  1. /* 
  2.  * syncSysV.c --
  3.  *
  4.  *    Do system V compatibility synchronization functions:
  5.  *        semctl, semget, semop
  6.  *
  7.  * Copyright (C) 1990 Regents of the University of California
  8.  * All rights reserved.
  9.  */
  10.  
  11. #ifndef lint
  12. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/sync/syncSysV.c,v 1.7 91/09/10 18:43:37 rab Exp $ SPRITE (Berkeley)";
  13. #endif /* not lint */
  14.  
  15. #include <sprite.h>
  16. #include <sync.h>
  17. #include <spriteTime.h>
  18. #include <fs.h>
  19. #include <stdio.h>
  20. #include <bstring.h>
  21. #include <vm.h>
  22. #include <stdlib.h>
  23.  
  24.  
  25. Sync_SysVSem semTable[SEMMNI];
  26. static int totalSems = 0;
  27.  
  28. static Sync_Lock semLock = Sync_LockInitStatic("Sync:sysVSemaphores");
  29. #define LOCKPTR (&semLock)
  30.  
  31. extern int vmShmDebug;
  32.  
  33. /*
  34.  * Debugging print statement declaration.
  35.  */
  36. #ifndef lint 
  37. #define dprintf if (vmShmDebug) printf
  38. #else
  39. #define dprintf printf
  40. #endif
  41.  
  42. /*
  43.  * Compat. defs.
  44.  */
  45. #define EPERM    GEN_EPERM
  46. #define ENOENT    GEN_ENOENT
  47. #define EINTR    GEN_EINTR
  48. #define EACCES    GEN_EACCES
  49. #define EEXIST    GEN_EEXIST
  50. #define EINVAL    GEN_EINVAL
  51. #define ENOSPC    GEN_ENOSPC
  52.  
  53. #define EFBIG    GEN_EFBIG
  54. #define    E2BIG    GEN_E2BIG
  55. #define EAGAIN    GEN_EAGAIN
  56. #define EFAULT    GEN_EFAULT
  57. #define ERANGE    GEN_ERANGE
  58. #define EIDRM    GEN_EIDRM
  59.  
  60. #define DEFAULTGID 115
  61.  
  62. static int semInit = 0;
  63.  
  64. /*
  65.  *----------------------------------------------------------------------
  66.  *
  67.  * Sync_SemInit --
  68.  *
  69.  *    Perform semaphore initialization functions.
  70.  *
  71.  * Results:
  72.  *    None.
  73.  *
  74.  * Side effects:
  75.  *    Initializes datastructures.
  76.  *
  77.  *----------------------------------------------------------------------
  78.  */
  79. void
  80. Sync_SemInit()
  81. {
  82.     int i;
  83.     if (semInit == 1234) {
  84.     return;
  85.     }
  86.     semInit = 1234;
  87.     LOCK_MONITOR;
  88.     for (i=0;i<SEMMNI;i++) {
  89.     semTable[i].sem_base = (struct sem *)NIL;
  90.     }
  91.     UNLOCK_MONITOR;
  92. }
  93.  
  94. /*
  95.  *----------------------------------------------------------------------
  96.  *
  97.  * Sync_SemctlStub --
  98.  *
  99.  *    Perform control functions on semaphores.
  100.  *
  101.  * Results:
  102.  *    Returns result of the function.
  103.  *
  104.  * Side effects:
  105.  *    Performs a function on the semaphore.
  106.  *
  107.  *----------------------------------------------------------------------
  108.  */
  109. ReturnStatus
  110. Sync_SemctlStub(semid, semnum, cmd, arg, retValOut)
  111.     int        semid;        /* Semaphore group identifier. */
  112.     int        semnum;        /* Semaphore number. */
  113.     int        cmd;        /* Command to perform. */
  114.     union semun    arg;        /* Command argument. */
  115.     int        *retValOut;    /* Result of command. */
  116. {
  117.  
  118.     ReturnStatus    status;
  119.     int            perm;
  120.     Sync_SysVSem    *semPtr;
  121.     int            uid;
  122.     struct semid_ds    semBuf;
  123.     int            i;
  124.     int            nsems;
  125.     struct sem        *curSem;
  126.     ushort        array[SEMMSL];
  127.     Time        timeVal;
  128.     int            retVal=0;
  129.  
  130.     dprintf("call: semctl(%d, %d, %d, %x)\n", semid, semnum, cmd, arg);
  131.     Sync_SemInit();
  132.     LOCK_MONITOR;
  133.     if (cmd != GETKEYS) {
  134.     status = Sync_SemStruct(semid, &perm, &semPtr);
  135.     if (status != SUCCESS) {
  136.         UNLOCK_MONITOR;
  137.         return status;
  138.     }
  139.     }
  140.     switch (cmd) {
  141.  
  142.     case SETVAL:
  143.     case SETALL:
  144.         if (!(perm & SEM_A)) {
  145.         UNLOCK_MONITOR;
  146.         dprintf("Access denied\n");
  147.         return EACCES;
  148.         }
  149.         break;
  150.     case IPC_SET:
  151.     case IPC_RMID:
  152.         uid=Proc_GetEffectiveProc()->effectiveUserID;
  153.         if (uid != 0 && uid != semPtr->sem_perm.uid &&
  154.             uid != semPtr->sem_perm.cuid) {
  155.         UNLOCK_MONITOR;
  156.         dprintf("Permission denied\n");
  157.         return EPERM;
  158.         }
  159.         break;
  160.     case GETKEYS:
  161.         break;
  162.     case GETVAL:
  163.     case GETPID:
  164.     case GETNCNT:
  165.     case GETZCNT:
  166.     case GETALL:
  167.     case IPC_STAT:
  168.         if (!(perm & SEM_R)) {
  169.         UNLOCK_MONITOR;
  170.         dprintf("Access denied\n");
  171.         return EACCES;
  172.         }
  173.         break;
  174.     default:
  175.         UNLOCK_MONITOR;
  176.         dprintf("invalid command\n");
  177.         return EINVAL;
  178.     }
  179.         
  180.     if (cmd == GETVAL || cmd == SETVAL || cmd == GETPID || cmd == GETNCNT ||
  181.         cmd == GETZCNT) {
  182.     if (semnum < 0 || semnum >= semPtr->sem_nsems) {
  183.         UNLOCK_MONITOR;
  184.         dprintf("Invalid semnum: %d\n",semnum);
  185.         return EINVAL;
  186.     }
  187.     curSem = &semPtr->sem_base[semnum];
  188.     }
  189.     switch (cmd) {
  190.     case GETVAL:
  191.         retVal = curSem->semval;
  192.         dprintf("semctl(GETVAL) returns %d\n", retVal);
  193.         break;
  194.     case SETVAL:
  195.         if (arg.val < 0 || arg.val > SEMVMX) {
  196.         UNLOCK_MONITOR;
  197.         dprintf("Invalid value %d\n",arg.val);
  198.         return ERANGE;
  199.         }
  200.         curSem->semval = arg.val;
  201.         if ( (arg.val == 0 && curSem->semzcnt > 0) ||
  202.             (arg.val > 0 && curSem->semncnt > 0)) {
  203.         Sync_Broadcast(&curSem->semLock);
  204.         }
  205.         dprintf("semctl(SETVAL) returns %d\n", retVal);
  206.         break;
  207.     case GETPID:
  208.         retVal = curSem->sempid;
  209.         dprintf("semctl(GETPID) returns %d\n", retVal);
  210.         break;
  211.     case GETNCNT:
  212.         retVal = curSem->semncnt;
  213.         dprintf("semctl(GETNCNT) returns %d\n", retVal);
  214.         break;
  215.     case GETZCNT:
  216.         retVal = curSem->semzcnt;
  217.         dprintf("semctl(GETZCNT) returns %d\n", retVal);
  218.         break;
  219.     case GETALL:
  220.         for (i=0;i<semPtr->sem_nsems;i++) {
  221.         array[i] = semPtr->sem_base[i].semval;
  222.         }
  223.         status = Vm_CopyOut(sizeof(ushort)*semPtr->sem_nsems,
  224.             (Address) array, (Address) arg.array);
  225.         if (status != SUCCESS) {
  226.         UNLOCK_MONITOR;
  227.         dprintf("Copy-out fault\n");
  228.         return EFAULT;
  229.         }
  230.         dprintf("semctl(GETALL) done\n");
  231.         break;
  232.     case GETKEYS:
  233.         bzero((Address)&semBuf, sizeof(struct semid_ds));
  234.         for (i=0;i<SEMMNI;i++) {
  235.         semBuf.sem_perm.mode = semTable[i].sem_perm.mode;
  236.         semBuf.sem_perm.key = semTable[i].sem_perm.key;
  237.         semBuf.sem_perm.seq = semTable[i].sem_perm.seq;
  238.         semBuf.sem_perm.uid = semTable[i].sem_perm.uid;
  239.         semBuf.sem_perm.gid = semTable[i].sem_perm.gid;
  240.         semBuf.sem_nsems =
  241.             (semTable[i].sem_base == (struct sem *)NIL) ? 0 : 1;
  242.         status = Vm_CopyOut(sizeof(struct semid_ds), (Address) &semBuf,
  243.             (Address) (arg.buf+i));
  244.         if (status != SUCCESS) {
  245.             UNLOCK_MONITOR;
  246.             dprintf("Copy-out fault\n");
  247.             return EFAULT;
  248.         }
  249.         }
  250.         dprintf("semctl(GETALL) done\n");
  251.         break;
  252.     case IPC_STAT:
  253.         status = Vm_CopyOut(sizeof(struct semid_ds), (Address) semPtr,
  254.             (Address) arg.buf);
  255.         if (status != SUCCESS) {
  256.         UNLOCK_MONITOR;
  257.         dprintf("Copy-out fault\n");
  258.         return EFAULT;
  259.         }
  260.         dprintf("semctl(IPC_STAT) done\n");
  261.         break;
  262.     case SETALL:
  263.         status = Vm_CopyIn(sizeof(ushort)*semPtr->sem_nsems,
  264.             (Address) arg.array, (Address) array);
  265.         if (status != SUCCESS) {
  266.         UNLOCK_MONITOR;
  267.         dprintf("Copy-in fault\n");
  268.         return EFAULT;
  269.         }
  270.  
  271.         for (i=0;i<semPtr->sem_nsems;i++) {
  272.         if (array[i] < 0 || array[i] > SEMVMX) {
  273.             UNLOCK_MONITOR;
  274.             dprintf("Invalid value: %d\n",array[i]);
  275.             return ERANGE;
  276.         }
  277.         }
  278.         for (i=0;i<semPtr->sem_nsems;i++) {
  279.         semPtr->sem_base[i].semval = array[i];
  280.         }
  281.         for (i=0;i<semPtr->sem_nsems;i++) {
  282.         curSem = &semPtr->sem_base[i];
  283.         if ( (array[i] == 0 && curSem->semzcnt > 0) ||
  284.             (array[i] > 0 && curSem->semncnt > 0)) {
  285.             Sync_Broadcast(&curSem->semLock);
  286.         }
  287.         }
  288.         dprintf("semctl(SETALL) done\n");
  289.         break;
  290.     case IPC_SET:
  291.         status = Vm_CopyIn(sizeof(struct semid_ds), (Address) arg.buf,
  292.             (Address) &semBuf);
  293.         if (status != SUCCESS) {
  294.         UNLOCK_MONITOR;
  295.         dprintf("Copy-in fault\n");
  296.         return EFAULT;
  297.         }
  298.         semPtr->sem_perm.uid = semBuf.sem_perm.uid;
  299.         semPtr->sem_perm.gid = semBuf.sem_perm.gid;
  300.         semPtr->sem_perm.mode = semBuf.sem_perm.mode & 0666;
  301.         dprintf("semctl(IPC_SET) done\n");
  302.         break;
  303.     case IPC_RMID:
  304.         semPtr->sem_perm.seq++;
  305.         nsems = semPtr->sem_nsems;
  306.         if (nsems > SEMMNI) nsems = SEMMNI;
  307.         curSem = semPtr->sem_base;
  308.         semPtr->sem_base = (struct sem *)NIL;
  309.         semPtr->sem_perm.key = 0;
  310.         for (i=0;i<nsems;i++) {
  311.         if (curSem[i].semzcnt != 0 || curSem[i].semncnt != 0) {
  312.             Sync_Broadcast(&curSem->semLock);
  313.         }
  314.         }
  315.         free((char *)curSem);
  316.         dprintf("semctl(IPC_RMID) done\n");
  317.         break;
  318.     }
  319.     if (cmd == SETVAL || cmd == SETALL || cmd == IPC_SET) {
  320.     Timer_GetRealTimeOfDay(&timeVal, (int *)NIL, (Boolean *)NIL);
  321.     semPtr->sem_ctime = timeVal.seconds;
  322.     }
  323.     UNLOCK_MONITOR;
  324.     status = Vm_CopyOut(sizeof(int), (Address) &retVal, (Address) retValOut);
  325.     if (status != SUCCESS) {
  326.     dprintf("Copy-out fault\n");
  327.     return EFAULT;
  328.     }
  329.     return SUCCESS;
  330. }
  331.  
  332. /*
  333.  *----------------------------------------------------------------------
  334.  *
  335.  * Sync_SemgetStub --
  336.  *
  337.  *    Gets a set of semaphores.
  338.  *
  339.  * Results:
  340.  *    Returns result of the function.
  341.  *
  342.  * Side effects:
  343.  *    May create semaphore datastructures.
  344.  *
  345.  *----------------------------------------------------------------------
  346.  */
  347. ReturnStatus
  348. Sync_SemgetStub(key, nsems, semflg, retValOut)
  349.     long    key;        /* Semaphore key. */
  350.     int        nsems;        /* Number of semaphores requested. */
  351.     int        semflg;        /* Creation flag. */
  352.     int        *retValOut;    /* Result of operation. */
  353.     
  354. {
  355.     int            i;
  356.     Sync_SysVSem    *semPtr;
  357.     Proc_ControlBlock    *procPtr;
  358.     int            uid;
  359.     Time        timeVal;
  360.     int            retVal;
  361.     ReturnStatus    status;
  362.     Fs_ProcessState    *fsPtr;
  363.  
  364.     dprintf("call: semget(%d, %d, %d)\n", key, nsems, semflg);
  365.     Sync_SemInit();
  366.     if (nsems < 0 || nsems > SEMMSL) {
  367.     UNLOCK_MONITOR;
  368.     dprintf("Invalid number of semaphores: %d\n",nsems);
  369.     return EINVAL;
  370.     }
  371.     LOCK_MONITOR;
  372.     if (key != IPC_PRIVATE) {
  373.     /*
  374.      * Check if the key is in the semaphore table.
  375.      */
  376.     semPtr = NULL;
  377.     for (i=0;i<SEMMNI;i++) {
  378.         if ((long)semTable[i].sem_perm.key == key &&
  379.             semTable[i].sem_base != (struct sem *)NIL) {
  380.         semPtr = &semTable[i];
  381.         break;
  382.         }
  383.     }
  384.     if (semPtr == NULL && !(semflg & IPC_CREAT)) {
  385.         UNLOCK_MONITOR;
  386.         dprintf("No semaphore %d\n",key);
  387.         return ENOENT;
  388.     }
  389.     }
  390.     if (key == IPC_PRIVATE || semPtr == NULL) {
  391.     /*
  392.      * Want to create a new semaphore set.
  393.      */
  394.     if (nsems == 0) {
  395.         UNLOCK_MONITOR;
  396.         dprintf("Can't create 0 semaphores.\n");
  397.         return EINVAL;
  398.     }
  399.     semPtr = NULL;
  400.     for (i=0;i<SEMMNI;i++) {
  401.         if (semTable[i].sem_base == (struct sem *)NIL) {
  402.         semPtr = &semTable[i];
  403.         break;
  404.         }
  405.     }
  406.     if (semPtr == NULL) {
  407.         UNLOCK_MONITOR;
  408.         dprintf("Semaphore table full\n");
  409.         return ENOSPC;
  410.     }
  411.     if (totalSems+nsems > SEMMNS) {
  412.         UNLOCK_MONITOR;
  413.         dprintf("Semaphore table full\n");
  414.         return ENOSPC;
  415.     }
  416.     procPtr=Proc_GetEffectiveProc();
  417.     uid = procPtr->effectiveUserID;
  418.     semPtr->sem_perm.uid = procPtr->effectiveUserID;
  419.     semPtr->sem_perm.cuid = procPtr->effectiveUserID;
  420.     fsPtr = procPtr->fsPtr;
  421.     if (fsPtr->numGroupIDs > 0) {
  422.         semPtr->sem_perm.gid = fsPtr->groupIDs[0];
  423.     } else {
  424.         semPtr->sem_perm.gid = DEFAULTGID;
  425.     }
  426.     semPtr->sem_perm.cgid = semPtr->sem_perm.gid;
  427.     semPtr->sem_perm.mode = semflg&0666;
  428.     semPtr->sem_perm.key = key;
  429.     semPtr->sem_base = (struct sem *)malloc(sizeof(struct sem)*nsems);
  430.     Timer_GetRealTimeOfDay(&timeVal, (int *) NIL, (Boolean *) NIL);
  431.     semPtr->sem_nsems = nsems;
  432.     semPtr->sem_otime = 0;
  433.     semPtr->sem_ctime = timeVal.seconds;
  434.     for (i=0;i<nsems;i++) {
  435.         semPtr->sem_base[i].semval = 0;
  436.         semPtr->sem_base[i].sempid = 0;
  437.         semPtr->sem_base[i].semncnt = 0;
  438.         semPtr->sem_base[i].semzcnt = 0;
  439.     }
  440.     } else {
  441.     if (semPtr->sem_nsems < nsems) {
  442.         UNLOCK_MONITOR;
  443.         dprintf("Semaphore exists, but not enough semaphores.\n");
  444.         return EINVAL;
  445.     }
  446.     if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) {
  447.         UNLOCK_MONITOR;
  448.         dprintf("Semaphore set already exists\n");
  449.         return EEXIST;
  450.     }
  451.     if (((semflg & 0333) & semPtr->sem_perm.mode) != (semflg & 0333)) {
  452.         UNLOCK_MONITOR;
  453.         dprintf("Permission denied: mode %o\n",semPtr->sem_perm.mode);
  454.         return EACCES;
  455.     }
  456.     }
  457.     retVal = semPtr->sem_perm.seq*SEMMNI+(semPtr-semTable);
  458.     UNLOCK_MONITOR;
  459.     status = Vm_CopyOut(sizeof(int), (Address) &retVal, (Address) retValOut);
  460.     if (status != SUCCESS) {
  461.     dprintf("Copy-out failure\n");
  462.     return EFAULT;
  463.     }
  464.     dprintf("semget: returns %d\n",retVal);
  465.     return SUCCESS;
  466. }
  467.  
  468. /*
  469.  *----------------------------------------------------------------------
  470.  *
  471.  * Sync_SemopStub --
  472.  *
  473.  *    Perform semaphore operations on semaphores.
  474.  *
  475.  * Results:
  476.  *    Returns result of the function.
  477.  *
  478.  * Side effects:
  479.  *    Performs a function on the semaphore.
  480.  *
  481.  *----------------------------------------------------------------------
  482.  */
  483. ReturnStatus
  484. Sync_SemopStub(semid, sopsIn, nsops, retValOut)
  485.     int            semid;        /* Semaphore group identifier. */
  486.     struct sembuf    *sopsIn;    /* Operations to perform. */
  487.     int            nsops;        /* Number of operations. */
  488.     int            retValOut;    /* Result of operation. */
  489.     
  490. {
  491.     int            perms;
  492.     Sync_SysVSem    *semPtr;
  493.     ReturnStatus    status;
  494.     int            i,j;
  495.     struct sembuf    sops[SEMOPM];
  496.     int            seq;
  497.     int            semmod[SEMMSL];
  498.     Time        timeVal;
  499.     int            pid = Proc_GetEffectiveProc()->processID;
  500.     struct sem        *curSem;
  501.     int            retVal;
  502.     Boolean        sig;
  503.  
  504.     dprintf("call: semop(%d, %x, %d)\n", semid, sopsIn, nsops);
  505.  
  506.     if (nsops <= 0 || nsops > SEMOPM) {
  507.     dprintf("Too many semaphore operations\n");
  508.     return E2BIG;
  509.     }
  510.  
  511.     Sync_SemInit();
  512.  
  513.     status = Vm_CopyIn(sizeof(struct sembuf)*nsops, (Address) sopsIn,
  514.         (Address) sops);
  515.     if (status != SUCCESS) {
  516.     dprintf("Copy-in fault\n");
  517.     return EFAULT;
  518.     }
  519.     LOCK_MONITOR;
  520.     status = Sync_SemStruct(semid, &perms, &semPtr);
  521.     if (status != SUCCESS) {
  522.     UNLOCK_MONITOR;
  523.     return status;
  524.     }
  525.     for (i=0;i<nsops;i++) {
  526.     if (sops[i].sem_num < 0 || sops[i].sem_num >= semPtr->sem_nsems) {
  527.         UNLOCK_MONITOR;
  528.         dprintf("Semaphore value too big: #%d = %d, max: %d\n",
  529.             i, sops[i].sem_num, semPtr->sem_nsems);
  530.         return EFBIG;
  531.     }
  532.     if ((sops[i].sem_op != 0 && !(perms & SEM_A)) ||
  533.         (sops[i].sem_op == 0 && !(perms & SEM_R))) {
  534.         UNLOCK_MONITOR;
  535.         dprintf("Semaphore access denied\n");
  536.         return EACCES;
  537.     }
  538.     if (sops[i].sem_flg & SEM_UNDO) {
  539.         printf("semop: SEM_UNDO not implemented\n");
  540.         UNLOCK_MONITOR;
  541.         return EINVAL;
  542.     }
  543.     }
  544.  
  545. retry:
  546.  
  547.     status = SUCCESS;
  548.     for (i=0;i<nsops;i++) {
  549.     int sem_op = sops[i].sem_op;
  550.     curSem = &semPtr->sem_base[sops[i].sem_num];
  551.     retVal = curSem->semval;
  552.     if (sem_op < 0) {
  553.         if (curSem->semval >= -sem_op) {
  554.         curSem->semval -= -sem_op;
  555.         } else {
  556.         break;
  557.         }
  558.     } else if (sops[i].sem_op > 0) {
  559.         if (curSem->semval + sem_op > SEMVMX) {
  560.         status = ERANGE;
  561.         break;
  562.         }
  563.         curSem->semval += sem_op;
  564.     } else {
  565.         if (curSem->semval != 0) {
  566.         break;
  567.         }
  568.     }
  569.     }
  570.  
  571.     if (i==nsops) {
  572.     /*
  573.      * Success.
  574.      */
  575.     for (i=0;i<semPtr->sem_nsems;i++) {
  576.         semmod[i] = 0;
  577.     }
  578.     for (i=0;i<nsops;i++) {
  579.         semmod[sops[i].sem_num]++;
  580.     }
  581.     Timer_GetRealTimeOfDay(&timeVal, (int *)NIL, (Boolean *) NIL);
  582.     semPtr->sem_otime = timeVal.seconds;
  583.     for (i=0;i<semPtr->sem_nsems;i++) {
  584.         if (semmod[i] != 0) {
  585.         curSem = &semPtr->sem_base[i];
  586.         curSem->sempid = pid;
  587.         if ((curSem->semzcnt != 0 && curSem->semval == 0) ||
  588.             (curSem->semncnt != 0 && curSem->semval != 0)) {
  589.             Sync_Broadcast(&curSem->semLock);
  590.         }
  591.         }
  592.     }
  593.     UNLOCK_MONITOR;
  594.     status = Vm_CopyOut(sizeof(int), (Address) &retVal,
  595.         (Address) retValOut);
  596.     if (status != SUCCESS) {
  597.         dprintf("Copy-out fault\n");
  598.         return EFAULT;
  599.     }
  600.     return SUCCESS;
  601.     } else {
  602.     /*
  603.      * Failure;
  604.      */
  605.     /*
  606.      * Undo any changes.
  607.      */
  608.     for (j=0;j<i;j++) {
  609.         semPtr->sem_base[sops[j].sem_num].semval -= sops[j].sem_op;
  610.     }
  611.     if (status != SUCCESS) {
  612.         UNLOCK_MONITOR;
  613.         return status;
  614.     }
  615.     /*
  616.      * Wait if necessary.  Then try again.
  617.      */
  618.     if (!(sops[i].sem_flg & IPC_NOWAIT)) {
  619.         if (sops[i].sem_op == 0) {
  620.         curSem->semzcnt++;
  621.         } else {
  622.         curSem->semncnt++;
  623.         }
  624.         seq = semPtr->sem_perm.seq;
  625.         sig = Sync_Wait(&curSem->semLock, TRUE);
  626.         if (seq != semPtr->sem_perm.seq) {
  627.         UNLOCK_MONITOR;
  628.         dprintf("Semaphore removed\n");
  629.         return EIDRM;
  630.         }
  631.         if (sops[i].sem_op == 0) {
  632.         curSem->semzcnt--;
  633.         } else {
  634.         curSem->semncnt--;
  635.         }
  636.         if (sig) {
  637.         UNLOCK_MONITOR;
  638.         dprintf("Semaphore interrupted\n");
  639.         return EINTR;
  640.         } else {
  641.         goto retry;
  642.         }
  643.     } else {
  644.         UNLOCK_MONITOR;
  645.         dprintf("Semaphore would block\n");
  646.         return EAGAIN;
  647.     }
  648.     }
  649. }
  650.  
  651. /*
  652.  *----------------------------------------------------------------------
  653.  *
  654.  * Sync_SemStruct --
  655.  *
  656.  *    Get the semaphore structure, given the identifier.
  657.  *    This routine checks the associated permissions.
  658.  *
  659.  * Results:
  660.  *    Returns SUCCESS or error condition.
  661.  *
  662.  * Side effects:
  663.  *    None.
  664.  *
  665.  *----------------------------------------------------------------------
  666.  */
  667. ReturnStatus
  668. Sync_SemStruct(id, perm, retPtr)
  669.     int            id;        /* Semaphore id value. */
  670.     int            *perm;        /* (Return) permissions. */
  671.     Sync_SysVSem    **retPtr;    /* (Return) Semaphore structure. */
  672.  
  673. {
  674.     Sync_SysVSem    *semPtr;
  675.     Proc_ControlBlock    *procPtr;
  676.     int uid, gid;
  677.     int uperm;
  678.     Fs_ProcessState    *fsPtr;
  679.  
  680.     if (id < 0) return EINVAL;
  681.  
  682.     semPtr = &semTable[id%SEMMNI];
  683.     *retPtr = semPtr;
  684.     if (semPtr->sem_perm.seq != id/SEMMNI ||
  685.         semPtr->sem_base == (struct sem *) NIL ) {
  686.     /*
  687.      * No such semaphore.
  688.      */
  689.     dprintf("No semaphore %d\n",id);
  690.     return EINVAL;
  691.     }
  692.     /*
  693.      * Check permissions.
  694.      */
  695.     procPtr=Proc_GetEffectiveProc();
  696.     uid = procPtr->effectiveUserID;
  697.     fsPtr = procPtr->fsPtr;
  698.     if (fsPtr->numGroupIDs > 0) {
  699.     gid = fsPtr->groupIDs[0];
  700.     } else {
  701.     gid = DEFAULTGID;
  702.     printf("Warning: process has no gid\n");
  703.     }
  704.     if (uid == 0) {
  705.     *perm = SEM_A | SEM_R;
  706.     return SUCCESS;
  707.     }
  708.     if (uid == semPtr->sem_perm.uid || uid == semPtr->sem_perm.cuid) {
  709.     uperm = semPtr->sem_perm.mode;
  710.     } else if (gid == semPtr->sem_perm.gid || gid == semPtr->sem_perm.cgid) {
  711.     uperm = semPtr->sem_perm.mode<<3;
  712.     } else {
  713.     uperm = semPtr->sem_perm.mode<<6;
  714.     }
  715.     *perm = uperm & (SEM_A | SEM_R);
  716.     return SUCCESS;
  717. }
  718.